package graduation.project.testcase.strategy;

import graduation.project.body.OriginExpression;
import graduation.project.body.TestCase;
import graduation.project.body.TestCases;
import graduation.project.exception.NonExpressionException;
import graduation.project.utilities.Utility;

import java.util.ArrayList;
import java.util.LinkedHashSet;

public class MNFPGenerator implements TestSetGenerator {

	public TestCases generateTestCases(String expression, int testCaseNumber) {
		try {
			OriginExpression originEx;
			originEx = new OriginExpression(expression);
			return generateTestCases(originEx, testCaseNumber);
		} catch (NonExpressionException e) {
			System.out.println("the expression is not valid boolean expression");
			e.printStackTrace();
		}
		return null;
	}

	public TestCases generateTestCases(OriginExpression expression,
			int testCaseNumber) {
		
		TestCases result = new TestCases(expression.getExpression(), expression.getModel(), "MNFP");
		LinkedHashSet<TestCase> testSet = new LinkedHashSet<TestCase>();
		
		int[] maxdiff;
		int[][][] nfpSet = expression.getNfpSet();
		for(int i = 0; i < nfpSet.length; i++){
			for(int j = 0; j < nfpSet[i].length; j++){
				if(nfpSet[i][j].length <= 1){
					testSet.add(new TestCase(nfpSet[i][j][0], false));
				}else{
					maxdiff = Utility.getMaxDifferCells(nfpSet[i][j]);
					testSet.add(new TestCase(maxdiff[0], false));
					testSet.add(new TestCase(maxdiff[1], false));
					int and1 = maxdiff[0];
					int and2 = maxdiff[1];
					int or1 = and1;
					int or2 = and2;
					for(int k = 1; k < nfpSet[i][j].length; k++){
						if(((and1 != (and1 & nfpSet[i][j][k])) && (and2 != (and2 & nfpSet[i][j][k]))) || 
								((or1 != (or1 | nfpSet[i][j][k])) && (or2 != (or2 | nfpSet[i][j][k])))){
							testSet.add(new TestCase(nfpSet[i][j][k], false));
							and1 = and1 & nfpSet[i][j][k];
							or1 = or1 | nfpSet[i][j][k];
							and2 = and2 & nfpSet[i][j][k];
							or2 = or2 | nfpSet[i][j][k];
						}
					}
				}				
			}
		}
		ArrayList<TestCase> set = new ArrayList<TestCase>();
		set.addAll(testSet);
		result.setTestSet(set);
		return result;
	}
}
